// 创建通用的方法
export function isObject(obj) {
  return typeof obj === "object" && obj !== null;
}

export function def(data, key, value) {
  Object.defineProperty(data, key, {
    enumerable: false,
    configurable: false,
    value: value,
  });
}

// 代理取值的位置
export function proxy(vm, source, key) {
  Object.defineProperty(vm, key, {
    get() {
      return vm[source][key];
    },
    set(newVal) {
      vm[source][key] = newVal;
    },
  });
}

// 合并option ，Vue内部的和用户传入的
export function mergeOptions(parent, child) {
  const options = {};
  // 遍历parent中的值
  for (let key in parent) {
    mergeField(key);
  }
  // 遍历child中的值
  for (let key in child) {
    if (!parent.hasOwnProperty(key)) {
      //只遍历parent中不存在的
      mergeField(key);
    }
  }
  function mergeField(key) {
    if (strats[key]) {
      return (options[key] = strats[key](parent[key], child[key]));
    }
    // parent child all object
    if (typeof parent[key] === "object" && typeof child[key] === "object") {
      options[key] = {
        ...parent[key],
        ...child[key],
      };
    } else if (child[key] == null) {
      options[key] = parent[key];
    } else {
      options[key] = child[key];
    }
  }
  return options;
}

const LIFECYCLE_HOOKS = [
  "beforeCreate",
  "created",
  "beforeMount",
  "mounted",
  "beforeUpdate",
  "updated",
  "beforeDestroy",
  "destroyed",
];

let strats = {};
LIFECYCLE_HOOKS.forEach((hook) => {
  strats[hook] = mergeHook;
});
function mergeHook(parentVal, childVal) {
  if (childVal) {
    if (parentVal) {
      return parentVal.concat(childVal);
    } else {
      return [childVal];
    }
  } else {
    return parentVal;
  }
}

// 添加组件的合并策略
strats.components = mergeAssets;

// 定义的组件，如果全局和组件内同时存在，不能进行合并覆盖。创建单独合并策略，把全局的组件放到原型链中
function mergeAssets(parentVal, childVal) {
  // res 创建出原型为parentVal的对象
  // Object.create()方法创建一个新对象，使用现有的对象来提供新创建的对象的__proto__
  const res = Object.create(parentVal); // res.__proto__ = parentVal
  if(childVal){
    for(let key in childVal){
      res[key] = childVal[key];
    }
  }
  return res;
}
